package com.kun.service.service.impl;

import com.kun.dto.PageTable;
import com.kun.dto.ProcessDefinitionDto;
import com.kun.service.service.IProcessDefinitionService;
import com.kun.vo.ProcessDefinitionVo;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.zip.ZipInputStream;

@Service
public class ProcessDefinitionServiceImpl implements IProcessDefinitionService {

    private final RepositoryService repositoryService;

    public ProcessDefinitionServiceImpl(RepositoryService repositoryService) {
        this.repositoryService = repositoryService;
    }

    /**
     * 查询单个流程定义
     */
    @Override
    public ProcessDefinition selectByDefinitionId(String definitionId) {
        return repositoryService.createProcessDefinitionQuery()
                .processDefinitionId(definitionId).singleResult();
    }

    /**
     * 查询流程定义列表
     */
    @Override
    public PageTable selectDefinitionList(ProcessDefinitionDto processDefinitionDto) {
        // 起始页
        int firstResult = (processDefinitionDto.getCurrent() - 1) * processDefinitionDto.getPageSize();
        // 用于执行查询流程定义
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
        // 获取流程定义数据
        List<ProcessDefinition> list = processDefinitionQuery.listPage(firstResult, processDefinitionDto.getPageSize());
        // 获取流程定义的总数
        long count = processDefinitionQuery.count();
        List<ProcessDefinitionVo> list1 = list.stream().map(processDefinition ->
                new ProcessDefinitionVo(processDefinition.getName(), processDefinition.getKey(),
                        processDefinition.getVersion(), processDefinition.getResourceName(),
                        processDefinition.getDeploymentId())).toList();
        return new PageTable(list1, count);
    }

    @Override
    public List<ProcessDefinitionVo> selectList() {
        List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();
        return list.stream().map(processDefinition ->
                new ProcessDefinitionVo(processDefinition.getName(), processDefinition.getKey(),
                        processDefinition.getVersion(), processDefinition.getResourceName(),
                        processDefinition.getDeploymentId())).toList();
    }

    /**
     * 根据流程定义ID查询流程定义
     */
    @Override
    public ProcessDefinitionVo selectListById(List<ProcessDefinitionVo> processDefinitionVoList,
                                              String processDefinitionId) {
        return processDefinitionVoList.stream()
                .filter(processDefinitionVo -> processDefinitionVo.getDeploymentId().equals(processDefinitionId))
                .findFirst().orElse(null);
    }

    /**
     * 获取流程定义的xml文件
     */
    @Override
    public String getXml(String deploymentId, String resourceName) {
        // 获取流程定义的资源文件，返回的是一个 InputStream 对象，用于读取该资源的内容。
        try (InputStream resourceAsStream = repositoryService.getResourceAsStream(deploymentId, resourceName)) {
            return IOUtils.toString(resourceAsStream, StandardCharsets.UTF_8);
        } catch (IOException e) {
            throw new RuntimeException("获取流程定义失败", e);
        }
    }

    /**
     * 保存流程定义
     */
    @Override
    public boolean saveDefinition(String xml, String name) {
        repositoryService.createDeployment().addString("createWithBpmnJs-" + name + ".bpmn", xml)
                .name(name).deploy();
        return true;
    }

    /**
     * 上传流程定义文件
     */
    @Override
    public boolean uploadBpmn(List<MultipartFile> files) {
        files.forEach(file -> {
            // 获取文件名
            String filename = file.getOriginalFilename();
            String name = filename + "---" + System.currentTimeMillis();
            // 获取文件扩展名
            String extension = FilenameUtils.getExtension(filename);
            // 获取文件流
            try (InputStream inputStream = file.getInputStream()) {
                if ("zip".equalsIgnoreCase(extension)) {
                    try (ZipInputStream zipInputStream = new ZipInputStream(inputStream)) {
                        repositoryService.createDeployment().addZipInputStream(zipInputStream).name(name).deploy();
                    }
                } else {
                    repositoryService.createDeployment().addInputStream(filename, inputStream).name(name).deploy();
                }
            } catch (IOException e) {
                throw new RuntimeException("文件上传失败：" + e);
            }
        });
        return true;
    }

    /**
     * 删除流程定义
     */
    @Override
    public boolean deleteDefinitionById(String processDefinitionId) {
        // true 表示所有的历史都删掉
        repositoryService.deleteDeployment(processDefinitionId, true);
        return true;
    }
}
